﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Codemonk.Common.Caching;
using Codemonk.Common.Emit;

namespace Codemonk.Common.Injection
{
    public sealed class ContainerBuilder : IContainerBuilder
    {
        private TypeAccessorFactory accessorFactory = new TypeAccessorFactory();

        private ICacheCollection<Type, Type> typeCache = new TypeDictionary<Type>();

        private ICacheCollection<Type, object> instanceCache = new TypeDictionary<object>();

        private ICacheCollection<Type, Func<object>> funcCache = new TypeDictionary<Func<object>>();


        private Func<object> CreateCtor(Type type)
        {
            return new Func<object>(() =>
            {
                var accessor = accessorFactory.GetByType(type);



                return null;
            });
        }

        public void RegisterType<T>(LifeStyle style)
        {
            throw new NotImplementedException();
        }

        public void Regist<T, I>(LifeStyle style)
        {
            throw new NotImplementedException();
        }

        public void RegisterInstance<T>(T instance)
        {
            funcCache.Set(typeof(T), () => instance);
        }

        public void Register<T>(Func<T> creater, LifeStyle style)
        {
            if (creater == null) return;
            if (style == LifeStyle.Singleton)
            {
                //利用拟闭包性质来创建单例
                object sync = new object();
                T obj = default(T);
                funcCache.Set(typeof(T), () =>
                {
                    if (obj == null)
                    {
                        lock (sync)
                        {
                            if (obj == null)
                            {
                                obj = creater();
                            }
                        }
                    }
                    return obj;
                });
            }
            else
            {
                funcCache.Set(typeof(T), () => creater());
            }
        }

        public I Resolve<I>()
        {
            Type interfaceType = typeof(I);
            Func<object> func;
            if (funcCache.TryGet(interfaceType, out func)) return (I)func();
            return default(I);
        }
    }
}
